import cv2
from starlette.middleware.cors import CORSMiddleware
import detection_face as detection_face
import recognition_face as recognition_face
from fastapi import FastAPI, HTTPException
import uvicorn

import os
from fastapi import FastAPI, UploadFile, File, HTTPException
from fastapi.responses import FileResponse, JSONResponse
from fastapi.middleware.cors import CORSMiddleware
from typing import List
import shutil
from pathlib import Path

# 创建 FastAPI 应用实例
app = FastAPI(title="幼儿园时光缩影",
              description="幼儿园时光缩影功能相关服务接口",
              version="1.0.0")

# 配置CORS中间件
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# 配置上传文件夹和允许的扩展名
UPLOAD_FOLDER = "uploads"
ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif', 'zip', 'rar', 'doc', 'docx'}

# 确保上传文件夹存在
Path(UPLOAD_FOLDER).mkdir(exist_ok=True)


def allowed_file(filename: str) -> bool:
    return '.' in filename and \
        filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS


def get_file_size(file_path: str) -> str:
    """获取文件大小并转换为易读格式"""
    size = os.path.getsize(file_path)
    for unit in ['B', 'KB', 'MB', 'GB']:
        if size < 1024:
            return f"{size:.2f} {unit}"
        size /= 1024
    return f"{size:.2f} TB"


@app.post("/upload/", summary="上传文件")
async def upload_file(file: UploadFile = File(...)):
    """
    上传文件接口

    - **file**: 必须，要上传的文件
    """
    if not allowed_file(file.filename):
        raise HTTPException(
            status_code=400,
            detail=f"文件类型不支持，支持的类型: {', '.join(ALLOWED_EXTENSIONS)}"
        )

    # 安全处理文件名
    file_path = os.path.join(UPLOAD_FOLDER, file.filename)

    # 如果文件已存在，添加后缀避免覆盖
    counter = 1
    while os.path.exists(file_path):
        name, ext = os.path.splitext(file.filename)
        file_path = os.path.join(UPLOAD_FOLDER, f"{name}_{counter}{ext}")
        counter += 1

    # 保存文件
    try:
        with open(file_path, "wb") as buffer:
            shutil.copyfileobj(file.file, buffer)
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"文件保存失败: {str(e)}")
    finally:
        await file.close()

    return JSONResponse(
        content={
            "message": "文件上传成功",
            "filename": os.path.basename(file_path),
            "path": file_path,
            "size": get_file_size(file_path)
        },
        status_code=201
    )


@app.get("/download/{filename}", summary="下载文件")
async def download_file(filename: str):
    """
    下载文件接口

    - **filename**: 要下载的文件名
    """
    file_path = os.path.join(UPLOAD_FOLDER, filename)

    if not os.path.exists(file_path):
        raise HTTPException(status_code=404, detail="文件不存在")

    return FileResponse(
        path=file_path,
        filename=filename,
        media_type='application/octet-stream'
    )


@app.get("/files/", summary="获取文件列表", response_model=List[dict])
async def list_files():
    """获取已上传文件列表"""
    files = []
    for filename in os.listdir(UPLOAD_FOLDER):
        file_path = os.path.join(UPLOAD_FOLDER, filename)
        if os.path.isfile(file_path):
            files.append({
                "name": filename,
                "size": get_file_size(file_path),
                "path": file_path,
                "last_modified": os.path.getmtime(file_path)
            })

    return files


@app.delete("/files/{filename}", summary="删除文件")
async def delete_file(filename: str):
    """
    删除文件接口

    - **filename**: 要删除的文件名
    """
    file_path = os.path.join(UPLOAD_FOLDER, filename)

    if not os.path.exists(file_path):
        raise HTTPException(status_code=404, detail="文件不存在")

    try:
        os.remove(file_path)
        return JSONResponse(
            content={"message": f"文件 {filename} 已删除"},
            status_code=200
        )
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"删除文件失败: {str(e)}")




# 在视频中摘选目标人脸图像帧合成视频
@app.post("/videoAnalysis", summary="在视频中摘选目标人脸图像帧合成视频")
def videoAnalysis(request: dict):
    # # 输入视频路径和输出视频路径
    # target_face_img = './data/images/me.jpg'   #目标人脸图像
    # video_path = './data/videos/video1.mp4'  # 输入视频路径
    # output_video_path = './data/videos/output_video2.mp4'  # 输出视频路径


    target_face_img = './data/xinghuo/boy1.jpg'  # 目标人脸图像
    video_path = './data/xinghuo/video2.mp4'  # 输入视频路径
    output_video_path = './data/xinghuo/output_video.mp4'  # 输出视频路径

    target_face_img = request.get("target_face_img")
    video_path = request.get("video_path")
    output_video_path = request.get("output_video_path")


    my_detection_face = detection_face.DetectionFace()
    my_recognition_face = recognition_face.RecognitionFace()

    #对视频进行目标人脸图像的检测识别与生成最终视频
    test(target_face_img,video_path,output_video_path,my_detection_face,my_recognition_face)

    return {"code": 201, "data": ""}


def test(target_face_img,video_path,output_video_path,my_detection_face,my_recognition_face):

    # 打开视频文件
    cap = cv2.VideoCapture(video_path)
    if not cap.isOpened():
        print("Error opening video file")
        exit()

    # 获取视频的帧率和尺寸
    fps = cap.get(cv2.CAP_PROP_FPS)
    frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

    # 初始化视频写入器
    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    out = cv2.VideoWriter(output_video_path, fourcc, fps, (frame_width, frame_height))

    # 假设GOP大小为12（常见值）
    gop_size = 12
    frame_index = 0

    while cap.isOpened():
        ret, frame = cap.read()
        if not ret:
            break
        # 判断是否为关键帧
        if frame_index % gop_size == 0:
            #检测当前帧图像中是否有人脸
            detected_face_collection = my_detection_face.get_detected_face_collection(frame)# 检测到的人脸集合（各人脸矩形框坐标信息）
            target_face_coordinate = my_recognition_face.get_target_face_coordinate(target_face_img,detected_face_collection,frame)#
            # print("当前帧图像:",frame)
            #检测当前帧图像中是否有目标
            #展示当前帧图像,并红色框选住检测到的目标人脸坐标位置信息

            if target_face_coordinate:
                # 指定矩形框的位置，coordinates 为 [xmin, ymin, xmax, ymax]
                # xmin, ymin, xmax, ymax = target_face_coordinate # 这里替换为你的四个点的坐标
                # # 计算宽度和高度
                # width = xmax - xmin
                # height = ymax - ymin
                # # 创建一个红色矩形框
                # rect = patches.Rectangle((xmin, ymin), width, height, linewidth=2, edgecolor='red', facecolor='none')
                # # 将矩形框添加到图像中
                # plt.gca().add_patch(rect)
                #
                # plt.imshow(frame)
                # for i in range(20):
                out.write(frame)
                print(f"Key frame written at index {frame_index}")

        frame_index += 1

    # 释放资源
    cap.release()
    out.release()
    cv2.destroyAllWindows()

def main():
    # 使用 uvicorn 运行 FastAPI 应用
    uvicorn.run(app, host="0.0.0.0", port=8000)

if __name__ == "__main__":
    main()